﻿using System;
using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Data;
using GrainManage.Base;
using System.Reflection;
using GrainManage.Proxy;

namespace GrainManage.Tools
{
    public sealed class UIHelper : IShowContent
    {
        private static readonly object LockObject = new object();
        private GridView LastView;
        private string LastModel;
        private readonly System.Windows.Threading.Dispatcher Dispatcher;
        private static readonly Dictionary<string, string> headerCollection = new Dictionary<string, string>();
        private const string cmdGetHeader = "SELECT Header FROM ColumnInfo WHERE ColumnName=?";

        public UIHelper(System.Windows.Threading.Dispatcher dispatcher)
        {
            this.Dispatcher = dispatcher;
        }

        private string GetHeader(string column)
        {
            if (!headerCollection.ContainsKey(column))
            {
                //var result = ColumnProxy.GetHeader(column);
                var result = SQLite.ExecuteScalar(cmdGetHeader, column);
                headerCollection[column] = result == null ? column : Convert.ToString(result);
            }
            return headerCollection[column];
        }

        private GridView GenerateGridView<TModel>() where TModel : class
        {
            var type = typeof(TModel).Name;
            if (LastModel == type)
            {
                return LastView;
            }
            var gridView = new GridView();
            var mediaType = typeof(byte[]);
            var timeType = typeof(DateTime?);
            var modelType = typeof(TModel);
            foreach (var property in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
            {
                var viewColumn = new GridViewColumn();
                var header = new GridViewColumnHeader();
                var columnName = property.Name;
                header.Content = GetHeader(columnName);
                header.Tag = columnName;
                viewColumn.Header = header;

                FrameworkElementFactory cellView = new FrameworkElementFactory();
                var columnType = property.PropertyType;
                if (columnType == mediaType)
                {
                    cellView.Type = typeof(Image);
                    cellView.SetValue(Image.WidthProperty, 80d);
                    cellView.SetValue(Image.HeightProperty, 60d);
                    cellView.SetValue(Image.MaxWidthProperty, 80d);
                    cellView.SetValue(Image.MaxHeightProperty, 60d);
                    cellView.SetBinding(Image.SourceProperty, new Binding(columnName));
                }
                else
                {
                    cellView.Type = typeof(TextBlock);
                    cellView.SetValue(TextBlock.MinWidthProperty, 80d);
                    cellView.SetValue(TextBlock.MaxWidthProperty, 160d);
                    var binding = new Binding(columnName);
                    if (columnType == timeType)
                    {
                        binding.StringFormat = columnName == "BirthDate" ? "{0:yyyy-MM-dd}" : "{0:yyyy-MM-dd HH:mm:ss}";
                    }
                    cellView.SetBinding(TextBlock.TextProperty, binding);
                    //AddSortColumnEvent(header);
                }

                var template = new DataTemplate();

                template.VisualTree = cellView;
                viewColumn.CellTemplate = template;
                gridView.Columns.Add(viewColumn);
            }

            lock (LockObject)
            {
                LastModel = type;
                LastView = gridView;
            }
            return gridView;
        }

        private void BeginInvokeUI(Action uiAction)
        {
            Dispatcher.BeginInvoke(uiAction, System.Windows.Threading.DispatcherPriority.Background);
        }

        public void ShowContent<TModel>(ListView listView, List<TModel> models) where TModel : class
        {
            BeginInvokeUI(() =>
            {
                listView.View = GenerateGridView<TModel>();
                listView.ItemsSource = models;
                //listView.DataContext = data.Tables[0];
                //listView.SetBinding(ListView.ItemsSourceProperty, string.Empty);
            });

        }

        public void ShowContent(ComboBox combo, List<string> data)
        {
            BeginInvokeUI(() =>
            {
                combo.ItemsSource = data;
            });
        }

    }
}
